/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package de.blitzcoder.collide.gui;

import de.blitzcoder.collide.Config;
import de.blitzcoder.collide.util.Log;
import java.awt.Color;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.ListIterator;
import javax.swing.JTextArea;
import javax.swing.text.DefaultHighlighter;

/**
 *
 * @author blitzcoder
 */
public class OutputTextArea extends JTextArea implements KeyListener {

    private byte[] inputBuffer = new byte[1024];
    private int bufferPos = 0;

    private static Color STDERR_COLOR = new Color(255,180,180);

    private boolean stdInEnabled = true;

    public OutputTextArea() {
        setToolTipText("Tippen sie einfach hier und bestätigen sie mit Return um etwas an den stdin des laufenden Prozesses zu senden.");
        addKeyListener(this);
        setLineWrap(false);
        setEditable(false);
        setFont(Config.getFontProperty("output.font"));
    }
    LinkedList<StdInListener> stdInListeners = new LinkedList<StdInListener>();

    public static interface StdInListener {

        public void stdIn(byte[] buf);
    }

    public void addStdInListener(StdInListener lis) {
        stdInListeners.addLast(lis);
    }

    public void removeAllStdInListeners() {
        stdInListeners.clear();
    }

    public void setStdInEnabled(boolean e) {
        stdInEnabled = e;
    }

    @Override
    public void append(String str) {
        super.append(str);
        // Ganz nach unten scrollen
        scrollRectToVisible(new Rectangle(new Point(0,getHeight()*2)));
    }

    @Override
    public void keyTyped(KeyEvent e) {

        if (!stdInEnabled)
            return;

        int code = e.getKeyChar();

        if (code == 0) {
            // Do nothing
        } else if (code == 8) { // Backspace

            if (bufferPos > 0) {

                // Delete last byte in buffer
                bufferPos--;

                // Delete last char in the TextArea
                setText(getText().substring(0, getText().length() - 1));

            }

        } else if (code == 10) { // Return

            // Send the buffer
            addToBuffer((byte)10);
            addToBuffer((byte)13);
            byte[] buf = Arrays.copyOfRange(inputBuffer, 0, bufferPos);
            ListIterator<StdInListener> it = stdInListeners.listIterator();
            while (it.hasNext()) {
                it.next().stdIn(buf);
            }

            System.out.println("Sent " + buf.length + " chars");

            // Clear the buffer
            bufferPos = 0;

            // Append a new line to the textarea
            append("\n");

        } else {

            if (!e.isActionKey()) {

                addToBuffer((byte)code);

                // Append to the TextArea
                append("" + e.getKeyChar());

            }

        }

        setCaretPosition(getText().length() - 1);
    }

    private void addToBuffer(byte b) {
        // Check if to much text is buffered
        if (bufferPos > inputBuffer.length - 1) {
            bufferPos = 0;
        }

        // Append to the buffer
        inputBuffer[bufferPos] = b;
        bufferPos++;
    }

    public void keyPressed(KeyEvent e) {
        setCaretPosition(getText().length() - 1);
    }

    public void keyReleased(KeyEvent e) {
        setCaretPosition(getText().length() - 1);
    }

    public void addStdErrorRegion(int start,int end) {
        try {
            Log.log(start+" "+end);
            getHighlighter().addHighlight(start, end, new DefaultHighlighter.DefaultHighlightPainter(STDERR_COLOR));
        } catch (Exception ex) {
            throw new Error(ex);
        }
    }

}
